#include "mario.h"
#include <vector>
#include <typeinfo>
#include "Engine2D/dxgameinput.h"
#include "coin.h"
#include "mushroom.h"

Mario::Mario(QuadTree<GameObject>* quadtree, int w, int h, float x, float y, float _big) : DynamicObject()
{	
    worldMap = quadtree;
    widthScreen = w;
    heightScreen = h;
    if (mSprite.find("mario") == mSprite.end())
    {	
        char path[100] = "Data\\mario.bmp";
        mSprite["mario"] = new DXSprite(path, D3DCOLOR_XRGB(0, 0, 0), 2, 8);
    }
    pSprite = mSprite["mario"];
    posX = x;
    posY = y;
    layer = 10;
    originX = posX - widthScreen / 2;
    originY = 0;
    big = _big;
    pInput = DXGameInput::GetInstance();
    action[0] = Animation(pSprite, 1, 4);
    action[1] = Animation(pSprite, 9, 12);
    state = RIGHT_STAND;
    timeShift = 0;
    speed = SLOW_SPEED;
    move = 12;
    textSprite = new DXSprite("Data\\alphabet.png", D3DCOLOR_XRGB(255, 255, 255), 4, 13);
    text = Text(textSprite);
    score = 0;
    increase = score;
    life = 3;
}

Rect Mario::GetRectBound()
{	
    Rect bound = {posX, posY, posX + big * pSprite->GetWidth(), posY + big * pSprite->GetHeight()};
    return bound;
}

void Mario::Update(unsigned int gameTime)
{	
    Rect prevBound = this->GetRectBound();
    posY += move;
    if (state == RIGHT_SHIFT || state == LEFT_SHIFT)
        timeShift += gameTime;
    if ((state != RIGHT_JUMP) && (state != LEFT_JUMP) && (timeShift == 0 || timeShift >= 1000 / 10))
    {	
        test = true;
        timeShift = 0;
        if (pInput->IsKeyDown(DIK_RIGHT))
        {	
            if (state == LEFT_MOVE)
                state = RIGHT_SHIFT;
            else
                state = RIGHT_MOVE;
            if (originX + widthScreen < worldMap->GetWidthMap())
            {	
                if (speed == SLOW_SPEED)
                {	
                    originX += 4;
                    posX += 4;
                }
                else
                {	
                    originX += 8;
                    posX += 8;
                }
            }
        }
        else if (pInput->IsKeyDown(DIK_LEFT))
        {	
            if (state == RIGHT_MOVE)
                state = LEFT_SHIFT;
            else
                state = LEFT_MOVE;
            if (originX > 0)
            {	
                if (speed == SLOW_SPEED)
                {	
                    originX -= 4;
                    posX -= 4;
                }
                else
                {	
                    originX -= 8;
                    posX -= 8;
                }
            }
        }
        else if (pInput->IsKeyDown(DIK_DOWN))
        {	
            if (state == RIGHT_MOVE || state == RIGHT_STAND)
                state = RIGHT_DOWN;
            if (state == LEFT_MOVE || state == LEFT_STAND)
                state = LEFT_DOWN;
        }
        else if (state == RIGHT_MOVE || state == RIGHT_DOWN)
            state = RIGHT_STAND;
        else if (state == LEFT_MOVE || state == LEFT_DOWN)
            state = LEFT_STAND;
        if (pInput->IsKeyPress(DIK_SPACE))
        {	
            oldPosY = posY;
            posY -= (move + 12);
            if (state == RIGHT_MOVE || state == RIGHT_STAND)
                state = RIGHT_JUMP; 
            if (state == LEFT_MOVE || state == LEFT_STAND)
                state = LEFT_JUMP;
        }
        if (pInput->IsKeyDown(DIK_LSHIFT))
        {	
            speed = FAST_SPEED;
            jump = 220;
        }
        else
        {	
            speed = SLOW_SPEED;
            jump = 180;
        }
    }
    bool collide = false;
    vector<GameObject*> temp = worldMap->GetObjects(originX, 0, widthScreen, heightScreen);
    for (vector<GameObject*>::iterator i = temp.begin(); i != temp.end(); ++i)
    {	
        if (typeid(**i) != typeid(StaticObject))
        {	
            (*i)->Update(gameTime);
            if (IsCollide((*i)->GetRectBound(), this->GetRectBound()))
            {	
                if (typeid(**i) == typeid(Coin))
                {	
                    worldMap->RemoveObject(*i);
                    score += 200;
                }
                /*if (typeid(**i) == typeid(Mushroom))
                {	
                    if (((Mushroom*)(*i))->type == 1)
                    {	
                        if (big < 2.5) 
                            big = 2.5;
                    }
                    else
                        ++life;
                    worldMap->RemoveObject(*i);
                }*/
                if (typeid(**i) == typeid(DynamicObject))
                {	
                    if (prevBound.bottom <= ((*i)->GetRectBound()).top)
                        posY = ((*i)->GetRectBound()).top - big * pSprite->GetHeight();
                    else if (prevBound.top >= ((*i)->GetRectBound()).bottom)
                        posY = ((*i)->GetRectBound()).bottom;
                    else if (prevBound.right <= ((*i)->GetRectBound()).left)
                    {	
                        originX -= ((this->GetRectBound()).right - ((*i)->GetRectBound()).left);
                        posX -= ((this->GetRectBound()).right - ((*i)->GetRectBound()).left);
                    }
                    else if (prevBound.left >= ((*i)->GetRectBound()).right)
                    {	
                        originX += (((*i)->GetRectBound()).right - (this->GetRectBound()).left);
                        posX += (((*i)->GetRectBound()).right - (this->GetRectBound()).left);
                    }
                    if (state == RIGHT_JUMP)
                        state = RIGHT_STAND;
                    else if (state == LEFT_JUMP)
                        state = LEFT_STAND;
                    collide = true;
                }
            }
        }
    }
    if ((state == RIGHT_JUMP) || (state == LEFT_JUMP))
    {	
        if ((test == true) && (posY > oldPosY - jump))
            posY -= (move + 10);
        else
            test = false;
        if (pInput->IsKeyDown(DIK_RIGHT))
        {	
            state = RIGHT_JUMP;
            if (originX + widthScreen < worldMap->GetWidthMap())
            {	
                if (speed == SLOW_SPEED)
                {	
                    originX += 10;
                    posX += 10;
                }
                else
                {	
                    originX += 13;
                    posX += 13;
                }
            }
        }
        else if (pInput->IsKeyDown(DIK_LEFT))
        {	
            state = LEFT_JUMP;
            if (originX > 0)
            {	
                if (speed == SLOW_SPEED)
                {	
                    originX -= 10;
                    posX -= 10;
                }
                else
                {	
                    originX -= 13;
                    posX -= 13;
                }
            }
        }
    }
    if (increase != score)
    {	
        increase += 10;
        if (scale < 1)
            scale += 0.02;
    }
    else
        scale = 0.6;
    return;
}

void Mario::Render(unsigned int gameTime)
{	
    worldMap->Render(originX, 0, widthScreen, heightScreen, gameTime);
    pSprite->SetPosition(posX - originX, posY - originY);
    switch (state)
    {	
        case RIGHT_MOVE : action[0].Present(gameTime, speed, big); break;
        case LEFT_MOVE : action[1].Present(gameTime, speed, big); break;
        case RIGHT_SHIFT : pSprite->Draw(15, big); break;
        case LEFT_SHIFT : pSprite->Draw(7, big); break;
        case RIGHT_DOWN : pSprite->Draw(6, big); break;
        case LEFT_DOWN : pSprite->Draw(14, big); break;
        case RIGHT_JUMP : pSprite->Draw(5, big); break;
        case LEFT_JUMP : pSprite->Draw(13, big); break;
        case RIGHT_STAND : pSprite->Draw(0, big); break;
        case LEFT_STAND : pSprite->Draw(8, big); break;
    }
    text.Present("mario", 100, 10, 0.6);
    pSprite->SetPosition(widthScreen / 2 - 100, 10);
    pSprite->Draw(2, 1.2);
    text.Present("x", widthScreen / 2 - 75, 18, 0.4);
    text.Present(life, widthScreen / 2 - 55, 15, 0.5);
    text.Present(increase, widthScreen - 80, 10, scale);
    return;
}

Mario::~Mario()
{	
    if (textSprite != 0)
        delete textSprite;
}